import { deepClone } from './../../../../utils/lang';
import { FlatTreeControl } from '@angular/cdk/tree';
import { SelectionModel } from '@angular/cdk/collections';
import { SystemService } from '@service/system.service';
import { AbsFormUtil } from '@abstract/form';
import { Component, Input, OnInit, ViewChild } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { ISystemUser } from '@model/system';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalRef } from 'ng-zorro-antd/modal';
import { TreeService } from '@service/tree.service';
import { NzTreeFlatDataSource, NzTreeFlattener } from 'ng-zorro-antd/tree-view';
interface TreeNode {
	resName: string;
	disabled?: boolean;
	children?: TreeNode[];
	id: string;
    parentId?: string;
}

interface FlatNode {
	expandable: boolean;
	name: string;
	level: number;
	disabled: boolean;
	id: string;
    parentId?: string;
}
@Component({
	selector: 'app-system-role-edit',
	templateUrl: './system-role-edit.component.html',
	styleUrls: ['./system-role-edit.component.less']
})
export class SystemRoleEditComponent extends AbsFormUtil implements OnInit {
	@Input() id: number;
	nodes = [];
	flatNodeMap = new Map<FlatNode, TreeNode>();
	nestedNodeMap = new Map<TreeNode, FlatNode>();
	checklistSelection = new SelectionModel<string>(true);
	select = [];
	treeControl = new FlatTreeControl<FlatNode>(
		node => node.level,
		node => node.expandable
	);

    baseNodeIds = [];

	




	constructor(
		private nzMessageService: NzMessageService,
		private fb: FormBuilder,
		private nzModalRef: NzModalRef,
		private systemService: SystemService,
		private treeService: TreeService
	) {
		super();

	}

	ngOnInit() {
		
		this.buildForm();
		// if (this.item) {
		// 	this.validateForm.patchValue(this.item);
		// }
		
		
		if (this.id){
			this.getRoleInfo();
			return;
		}
		this.getResourceList();
	}
	private transformer = (node: TreeNode, level: number) => {
		const existingNode = this.nestedNodeMap.get(node);
		const flatNode =
			existingNode && existingNode.name === node.resName
				? existingNode
				: {
					expandable: !!node.children && node.children.length > 0,
					name: node.resName,
					level: level,
					id : node.id,
					disabled: !!node.disabled,
                    parentId: node.parentId.toString()
				};
		this.flatNodeMap.set(flatNode, node);
		this.nestedNodeMap.set(node, flatNode);
		return flatNode;
	};
	treeFlattener = new NzTreeFlattener(
		this.transformer,
		node => node.level,
		node => node.expandable,
		node => node.children
	);
	dataSource = new NzTreeFlatDataSource(this.treeControl, this.treeFlattener);
	

	hasChild = (_: number, node: FlatNode) => node.expandable;


	descendantsAllSelected(node: FlatNode): boolean {
		const descendants = this.treeControl.getDescendants(node);
		return (
			descendants.length > 0 &&
			descendants.every(child => {
				return this.checklistSelection.isSelected(child.id);
			})
		);
	}

	descendantsPartiallySelected(node: FlatNode): boolean {
		const descendants = this.treeControl.getDescendants(node);
		const result = descendants.some(child => this.checklistSelection.isSelected(child.id));
		return result && !this.descendantsAllSelected(node);
	}

	leafItemSelectionToggle(node: FlatNode): void {
		this.checklistSelection.toggle(node.id);
		this.checkAllParentsSelection(node);
	}

	itemSelectionToggle(node: FlatNode): void {
		this.checklistSelection.toggle(node.id);
		const descendants = this.treeControl.getDescendants(node);
		this.checklistSelection.isSelected(node.id)
			? this.checklistSelection.select(...descendants.map(it=>it.id))
			: this.checklistSelection.deselect(...descendants.map(it=>it.id));

		descendants.forEach(child => this.checklistSelection.isSelected(child.id));
		this.checkAllParentsSelection(node);
	}

	checkAllParentsSelection(node: FlatNode): void {
		let parent: FlatNode | null = this.getParentNode(node);
		while (parent) {
			this.checkRootNodeSelection(parent);
			parent = this.getParentNode(parent);
		}
	}

	checkRootNodeSelection(node: FlatNode): void {
		const nodeSelected = this.checklistSelection.isSelected(node.id);
		const descendants = this.treeControl.getDescendants(node);
		const descAllSelected =
			descendants.length > 0 &&
			descendants.every(child => {
				return this.checklistSelection.isSelected(child.id);
			});
		if (nodeSelected && !descAllSelected) {
			this.checklistSelection.deselect(node.id);
		} else if (!nodeSelected && descAllSelected) {
			this.checklistSelection.select(node.id);
		}
	}

	getParentNode(node: FlatNode): FlatNode | null {
		const currentLevel = node.level;
		if (currentLevel < 1) {
			return null;
		}
		const startIndex = this.treeControl.dataNodes.indexOf(node) - 1;
		for (let i = startIndex; i >= 0; i--) {
			const currentNode = this.treeControl.dataNodes[i];
			if (currentNode.level < currentLevel) {
				return currentNode;
			}
		}
		return null;
	}












	buildForm() {
		this.validateForm = this.fb.group({
			roleName: ['', Validators.required],
		});
	}
	async getRoleInfo() {
		const result = await this.systemService.getRoleInfo(this.id);
		const baseNodes = result.resources;
        console.log("🚀 ~ file: system-role-edit.component.ts ~ line 192 ~ SystemRoleEditComponent ~ getRoleInfo ~ baseNodes", baseNodes)
		this.validateForm.patchValue(result.sysRole);
		this.listToChildren(baseNodes);
		this.dataSource.setData(baseNodes);
		const select = this.treeControl.dataNodes.filter(it => this.select.includes(it.id));
		select.forEach(itm =>{
			this.leafItemSelectionToggle(itm);
		});
		
	}
	listToChildren(list: any[]) {
		if (list) {
			list.forEach(itm => {
				itm.children = itm.list || [];
				itm.resName = itm.name;
				itm.id = itm.value;
				if (!itm.list && itm.checked) {
					this.select.push(itm.id);
				}
				if (itm.list?.length) {
					this.listToChildren(itm.list);
				}
			});
		}
	}


	async getResourceList() {
		const result = await this.systemService.getResourceList();
		const baseNodes = this.treeService.convertListToTree(result.list, 0);
		this.dataSource.setData(baseNodes);
	}



	onSubmit() {
		this.markAsDirty();
		if (this.validateForm.invalid) {
			return;
		}
		const selectNode = this.treeControl.dataNodes.filter(it => this.checklistSelection.isSelected(it.id))
		if (!selectNode.length) {
			this.nzMessageService.error('权限不能为空');
			return
		}

      
	    const resourcelist = [];
        selectNode.forEach(it => {
            resourcelist.push(it.id);
            const parentIds = this.getParentIds(it.parentId);
            parentIds.forEach(id => {
                if (!resourcelist.includes(id)) {
                    resourcelist.push(id);
                }
            });
        })
		return {
			...this.validateForm.value,
			resourcelist
		}
		
	}

    getParentIds(parentId: string, result = []) {
        const parentItem = this.treeControl.dataNodes.find(it => it.id === parentId);
        if (parentItem) {
            result.push(parentItem.id);
            if (parentItem.parentId !== '0') {
               return this.getParentIds(parentItem.parentId, result);
            }
        }
        return result;
    }
	destroyModal() {
		this.nzModalRef.destroy();
	}
	expand() {
		this.treeControl.expandAll();
	}
	fold() {
		this.treeControl.collapseAll();
	}
	checkAll() {
		const select = this.treeControl.dataNodes.filter(it => !it.level);
		this.checklistSelection.clear();
		select.forEach(itm =>{
			this.itemSelectionToggle(itm);
		});
	}
	checkNoAll() {
		const select = this.treeControl.dataNodes.filter(it => !it.level);
		select.forEach(itm =>{
			this.checklistSelection.select(itm.id);
			this.itemSelectionToggle(itm);
		});
	}
	
}
